//
//  Mappable.swift
//  Wanke
//
//  Created by BO ZHOU on 2020/10/26.
//

import Foundation
fileprivate enum MapError: Error {
    case jsonToModelFail    //json转model失败
    case jsonToDataFail     //json转data失败
    case dictToJsonFail     //字典转json失败
    case jsonToArrFail      //json转数组失败
    case modelToJsonFail    //model转json失败
}


public protocol Mappable: Codable {

}




public extension Mappable {
    
    // MARK: 本地化
    
    /**
     * 归档
     */
    func encodeSelf(forKey: String) {
        
        SaveModelManager.sharedInstance.setObject(self, forKey: forKey)
    }
    
    func encodeSelf_asyn(forKey: String) {
        
        
        SaveModelManager.sharedInstance.setObject_asyn(self, forKey: forKey)
    }
    
    
    /**
     * 解档
     */
    static func decode(forKey: String) -> Self? {

        let obj: Self? = SaveModelManager.sharedInstance.objectForKey(forKey)
        return obj
    }
    
    static func decode_asyn(forKey: String, completionHandler: @escaping (Self?)->()) {

        SaveModelManager.sharedInstance.objectForKey_asyn(forKey, completionHandler: completionHandler)
    }

    
    /**
     * 删除
     */
    static func delete(forKey: String) {
        SaveModelManager.sharedInstance.removeObjectForKey(forKey)
    }
    
    func delete(forKey: String) {
        SaveModelManager.sharedInstance.removeObjectForKey(forKey)
    }
}


// MARK: 数组本地化
public extension Array where Element: Mappable {
    
    func encodeSelf(forKey: String) {
        
        SaveModelManager.sharedInstance.setObject(self, forKey: forKey)
    }
    
    func encodeSelf_asyn(forKey: String) {
        
        
        SaveModelManager.sharedInstance.setObject_asyn(self, forKey: forKey)
    }
    
    
    /**
     * 解档
     */
    static func decode(forKey: String) -> Self? {

        let obj: Self? = SaveModelManager.sharedInstance.objectForKey(forKey)
        return obj
    }
    
    static func decode_asyn(forKey: String, completionHandler: @escaping (Self?)->()) {

        SaveModelManager.sharedInstance.objectForKey_asyn(forKey, completionHandler: completionHandler)
    }
    
    /**
     * 删除
     */
    static func delete(forKey: String) {
        SaveModelManager.sharedInstance.removeObjectForKey(forKey)
    }
    
    func delete(forKey: String) {
        SaveModelManager.sharedInstance.removeObjectForKey(forKey)
    }
}


extension String: Mappable {}





// MARK: JSON---MODEL互相转化

import HandyJSON

public protocol JsonModelProtocol {
    
}

extension BaseModel: JsonModelProtocol {
    
}


public extension JsonModelProtocol where Self: BaseModel {
    
    /**
     *  Json转对象
     */
    static func fromJson(_ jsonStr: String) ->Self {
        if jsonStr == "" || jsonStr.count == 0 {
            #if DEBUG
            print("jsonoModel:字符串为空")
            #endif
            return Self.init()
        }
        
        return Self.deserialize(from: jsonStr)!
    }
    
    /**
     *  Json转数组对象
     */
    static func fromJsonArray(_ jsonArrayStr: String) ->[Self] {
        if jsonArrayStr == "" || jsonArrayStr.count == 0 {
            #if DEBUG
            print("jsonToModelArray:字符串为空")
            #endif
            return [Self]()
        }
        var modelArray: [Self] = []
        let data = jsonArrayStr.data(using: String.Encoding.utf8)
        let peoplesArray = try! JSONSerialization.jsonObject(with:data!, options: JSONSerialization.ReadingOptions()) as? [AnyObject]
        for people in peoplesArray! {
            modelArray.append(fromDictionary(people as! [String : Any]))
        }
        return modelArray
        
    }
    
    /**
     *  字典转对象
     */
    static func fromDictionary(_ dict: [String: Any]) ->Self {
        if dict.count == 0 {
            #if DEBUG
            print("dictionaryToModel:字符串为空")
            #endif
            return Self()
        }
        return Self.deserialize(from: dict)!
    }
    
    /**
     *  对象转JSON
     */
    func toJson() -> String {

        return (self.toJSONString())!
    }
    
    /**
     *  对象转字典
     */
    func toDictionary() -> [String: Any] {

        return (self.toJSON())!
    }
    
    
    //数组转json
    static func arrayToJson(_ array: NSArray) -> String {
        
        if (!JSONSerialization.isValidJSONObject(array)) {
            print("无法解析出JSONString")
            return ""
        }
        
        let data : NSData! = try? JSONSerialization.data(withJSONObject: array, options: []) as NSData
        let JSONString = NSString(data:data as Data,encoding: String.Encoding.utf8.rawValue)
        return JSONString! as String
        
    }
    
    /**
     * 字典转JSON
     */
    static func dictionaryToJson(_ dictionary:NSDictionary) -> String {
        if (!JSONSerialization.isValidJSONObject(dictionary)) {
            print("无法解析出JSONString")
            return ""
        }
        let data : NSData! = try? JSONSerialization.data(withJSONObject: dictionary, options: []) as NSData
        let JSONString = NSString(data:data as Data,encoding: String.Encoding.utf8.rawValue)
        return JSONString! as String
        
    }
}


public extension Dictionary {
    
    func toJsonString() -> String? {
        if !JSONSerialization.isValidJSONObject(self) {
            print("dict 转 json 失败")
            return nil
        }
        if let newData:Data = try? JSONSerialization.data(withJSONObject: self, options: []) {
            let JSONString = NSString.init(data: newData, encoding: String.Encoding.utf8.rawValue)
            return JSONString as String? ?? nil
        }
        print("dict 转 json 失败")
        return nil
    }
}

public extension Array {
    
    func toJsonString() -> String? {
        if !JSONSerialization.isValidJSONObject(self) {
            print("dict转json失败")
            return nil
        }
        if let newData : Data = try? JSONSerialization.data(withJSONObject: self, options: []) {
            let JSONString = NSString(data:newData as Data,encoding: String.Encoding.utf8.rawValue)
            return JSONString as String? ?? nil
        }
        print("dict转json失败")
        return nil
    }
    
  static func mapFromJson<T:Decodable>(_ jsonString:String,_ type:[T].Type) -> [T]? {
        guard let JSonData = jsonString.data(using: .utf8) else {
            return nil
        }
         let decoder = JSONDecoder()
        if let obj = try? decoder.decode(type, from: JSonData) {
            return obj
        }

        return nil
    }
}

public extension String {
    func toDict() -> [String:Any]? {
        guard let jsonData:Data = self.data(using: .utf8) else {
            print("json转dict失败")
            return nil
        }
        if let dict = try? JSONSerialization.jsonObject(with: jsonData, options: .mutableContainers) {
            return dict as? [String : Any] ?? ["":""]
        }
        print("json转dict失败")
        return nil
    }
    
    
    func toArray() -> Array<Any>? {
        
        let jsonData: Data = self.data(using: .utf8)!
        
        let array = try? JSONSerialization.jsonObject(with: jsonData, options: .mutableContainers)
        if array != nil {
            return array as? Array
        }
        return array as? Array
        
    }
}
